package com.xiangshizhineng.tianzhangzhi.app.service.impl;


import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiangshizhineng.tianzhangzhi.app.config.SmbConfig;
import com.xiangshizhineng.tianzhangzhi.app.dao.FileDAO;
import com.xiangshizhineng.tianzhangzhi.app.service.FileService;
import jcifs.smb.NtlmPasswordAuthentication;
import jcifs.smb.SmbFile;
import jcifs.smb.SmbFileOutputStream;
import org.apache.commons.io.IOUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.*;
import java.net.MalformedURLException;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Future;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@Service
public class FileServiceImpl extends ServiceImpl<FileDAO, com.xiangshizhineng.tianzhangzhi.app.model.entity.File> implements FileService {

    @Resource
    private SmbConfig smbConfig;

    private static Lock lock = new ReentrantLock();

    @Async("taskExecutor")
    @Override
    public Future<List<String>> upload(MultipartFile[] multipartFile){
        Future<List<String>> result = null;
        //上传,开启多线程 防止并发操作
        try {
            lock.lock();
            NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(smbConfig.getIp(), smbConfig.getName(), smbConfig.getPassword());
            SmbFile localFile = new SmbFile(smbConfig.getUrl(), auth);
            localFile.connect();
            List<String> list = smbFileUpload(smbConfig.getUrl(), multipartFile, auth);
            result = new AsyncResult<>(list);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        if (result == null) {
            result = new AsyncResult<>(null);
        }
        return result;
    }

    //向共享目录上传文件
    public  List<String> smbFileUpload(String remoteUrl,MultipartFile[] file,NtlmPasswordAuthentication auth) {
        List<String> list = new CopyOnWriteArrayList<>();
        try {
            for (MultipartFile multipartFile : file) {
                String uuid = UUID.randomUUID().toString();
                String name = multipartFile.getOriginalFilename();
                File localFile = multipartFileToFile(multipartFile, multipartFile.getOriginalFilename());
                SmbFile remoteFiles = new SmbFile(remoteUrl + File.separator + uuid + File.separator, auth);
                if (!remoteFiles.exists()) remoteFiles.mkdirs();
                SmbFile remoteFile = new SmbFile(remoteUrl + File.separator + uuid + File.separator + name, auth);
                InputStream in = new BufferedInputStream(new FileInputStream(localFile));
                OutputStream out = new BufferedOutputStream(new SmbFileOutputStream(remoteFile));
                IOUtils.copy(in, out);
                list.add("file"+File.separator+uuid+File.separator+name);
//                list.add(multipartFile.getOriginalFilename());
                out.close();
                in.close();
                if (localFile.exists()) {
                    localFile.delete();
                }
            }
        }catch(Exception e){
                e.printStackTrace();
            }
        return list;
        }

    public File multipartFileToFile(MultipartFile file,String name) throws Exception {

        File toFile = null;
        if (file.equals("") || file.getSize() <= 0) {
        } else {
            InputStream ins = file.getInputStream();
            toFile = new File(name);
            inputStreamToFile(ins, toFile);
        }
        return toFile;
    }
    private void inputStreamToFile(InputStream ins, File file) {
        try {
            OutputStream os = new FileOutputStream(file);
            IOUtils.copy(ins,os);
            os.close();
            ins.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
